import {
    ref,
    reactive,
    computed,
    watch,
    onMounted,
    onBeforeUnmount,
    defineComponent,
    withDirectives,
    resolveDirective,
    h,
    getCurrentInstance,
    toRefs,
    nextTick,
    toRef,
} from "vue"
import { provide } from "vue"
import useHooks from "amtf/hooks/use-hooks"
// import { util.深拷贝, debounce } from "lodash"
import { useDebounceFn } from "@vueuse/core"
import {
    initGroupColumns as util_initGroupColumns,
    getNotFixedTotalWidthByColumnKey,
    recursiveRemoveColumnByKey,
    setHeaderContextmenuOptions,
    setBodyContextmenuOptions,
    createEmptyRowData,
    isContextmenuPanelClicked,
    getRowKey,
    getColKeysByHeaderColumn,
    getColumnByColkey,
    getLeftmostColKey,
    isCellInSelectionRange,
    isClearSelectionByBodyCellRightClick,
    cellAutofill,
    isOperationColumn,
    getSelectionRangeData,
    getSelectionRangeKeys,
    getSelectionRangeIndexes,
    setColumnFixed,
    cancelColumnFixed,
} from "./util"
import {
    onBeforeCopy,
    onAfterCopy,
    onBeforePaste,
    onAfterPaste,
    onBeforeCut,
    onAfterCut,
    onBeforeDelete,
    onAfterDelete,
} from "./util/clipboard"
import { props } from "./props+"
import { isNumber, scrollTo, isEmptyValue, isEmptyArray, isDefined } from "amtf/utils"

import * as util from "amtf/utils"
import { KEY_CODES, MOUSE_EVENT_CLICK_TYPE } from "amtf/constants"
import { getScrollbarWidth } from "amtf/utils"
import { requestAnimationTimeout, cancelAnimationTimeout } from "amtf/utils"
import { isInputKeyCode } from "amtf/utils"
import { getMouseEventClickType } from "amtf/utils"
import { useEmitter } from "amtf/hooks"
import {
    COMPS_NAME,
    HOOKS_NAME,
    EMIT_EVENTS,
    COMPS_CUSTOM_ATTRS,
    INSTANCE_METHODS,
    CELL_SELECTION_DIRECTION,
    LOCALE_COMP_NAME,
    CONTEXTMENU_TYPES,
    CONTEXTMENU_NODE_TYPES,
    AUTOFILLING_DIRECTION,
    CURRENT_CELL_SELECTION_TYPES,
    COLUMN_FIXED_TYPE,
} from "./util/constant"

import Colgroup from "./colgroup"
import Header from "./header"
import Body from "./body"
import Footer from "./footer"
import EditInput from "./editor/index"
import Selection from "./selection/index"
import VueDomResizeObserver from "amtf/components/resize-observer"
import VeContextmenu from "amtf/components/contextmenu"
import ColumnResizer from "./column-resizer"
import { ClickOutside } from "amtf/directives"
import emitter from "amtf/utils/emitter"

import { use样式 } from "amtf/hooks"
import { getValByUnit, 拼组件名, isFunction, isBoolean, getRandomId } from "amtf/utils"
const 主名 = "table"
const 组件名 = 拼组件名(主名)

export default defineComponent({
    name: 组件名,
    directives: { "click-outside": ClickOutside },
    props,
    setup(props, { emit, expose }) {
        const { addHook, triggerHook } = useHooks()
        const instance = getCurrentInstance()
        const 表格id = instance.uid
        provide("表格id", 表格id)
        function emitterOn表格(event, fn) {
            emitter.on(表格id + event, fn)
        }
        // console.log(`instance.uid 👉`, instance.uid)
        const { 拼样式名_提前传主名 } = use样式(主名)

        const clickOutsideDirective = resolveDirective("click-outside")

        const { broadcast } = useEmitter(表格id)

        // 状态管理
        const a = reactive({
            // Hooks实例
            // 父组件是否已渲染
            parentRendered: false,
            // 表格视口宽度（除去滚动条宽度）
            tableViewportWidth: 0,
            // 列配置变化次数
            columnsOptionResetTime: 0,
            tableRootRef: "tableRootRef",
            tableContainerWrapperRef: "tableContainerWrapperRef",
            tableContainerRef: "tableContainerRef",
            tableRef: "tableRef",
            tableBodyRef: "tableBodyRef",
            tableContentWrapperRef: "tableContentWrapperRef",
            virtualPhantomRef: "virtualPhantomRef",
            editInputRef: "editInputRef",
            cellSelectionRef: "cellSelectionRef",
            contextmenuRef: "contextmenuRef",
            cloneColumns: [],
            // 是否是分组表头
            isGroupHeader: false,
            // 由groupColumns创建的表头行
            headerRows: [],
            // 由footerData创建的表尾行
            footerRows: [],
            colgroups: [],

            // 分组列
            groupColumns: [],
            // 存储当前隐藏列信息
            hiddenColumns: [],
            // 虚拟滚动可见数据
            virtualScrollVisibleData: [],
            // 虚拟滚动可见索引
            virtualScrollVisibleIndexs: {
                start: -1,
                end: -1,
            },
            // 默认虚拟滚动缓冲区比例
            defaultVirtualScrollBufferScale: 1,
            // 默认虚拟滚动最小行高
            defaultVirtualScrollMinRowHeight: 40,
            // 每次滚动默认的占位行数
            defaultPlaceholderPerScrollingRowCount: 8,
            // 起始索引
            virtualScrollStartIndex: 0,
            // 预览虚拟滚动起始索引
            previewVirtualScrollStartIndex: 0,
            // 结束索引
            virtualScrollEndIndex: 0,
            // 是否正在显示滚动占位符
            showVirtualScrollingPlaceholder: false,
            // 禁用指针事件的超时ID
            disablePointerEventsTimeoutId: null,
            // 是否正在向左滚动
            isLeftScrolling: false,
            // 是否正在向右滚动
            isRightScrolling: false,
            // 是否正在垂直滚动
            isVerticalScrolling: false,
            // 是否有水平滚动条
            hasXScrollBar: false,
            // 是否有垂直滚动条
            hasYScrollBar: false,
            // 滚动条宽度
            scrollBarWidth: 0,
            // 预览表格容器的scrollLeft（用于处理左列或右列固定效果）
            previewTableContainerScrollLeft: null,
            // 表头单元格选择的列键
            headerIndicatorColKeys: {
                startColKey: "",
                startColKeyIndex: -1,
                endColKey: "",
                endColKeyIndex: -1,
            },
            // 表体指示行键
            bodyIndicatorRowKeys: {
                startRowKey: "",
                startRowKeyIndex: -1,
                endRowKey: "",
                endRowKeyIndex: -1,
            },
            // 单元格选择数据
            cellSelectionData: {
                currentCell: {
                    rowKey: "",
                    colKey: "",
                    rowIndex: -1,
                },
                normalEndCell: {
                    rowKey: "",
                    colKey: "",
                    rowIndex: -1,
                },
                autoFillEndCell: {
                    rowKey: "",
                    colKey: "",
                },
            },
            // 单元格选择范围数据
            cellSelectionRangeData: {
                leftColKey: "",
                rightColKey: "",
                topRowKey: "",
                bottomRowKey: "",
            },
            // 表头单元格是否按下鼠标
            isHeaderCellMousedown: false,
            // 表体单元格是否按下鼠标
            isBodyCellMousedown: false,
            // 表体操作列是否按下鼠标
            isBodyOperationColumnMousedown: false,
            // 是否开始自动填充
            isAutofillStarting: false,
            // 自动填充方向
            autofillingDirection: null,
            // 当前单元格选择类型
            currentCellSelectionType: "",
            // 表格偏移高度（开启虚拟滚动时使用）
            tableOffestHeight: 0,
            // 表格高度
            tableHeight: 0,
            // 高亮行键
            highlightRowKey: "",
            // 正在编辑的单元格
            editingCell: {
                rowKey: "",
                colKey: "",
                row: null,
                column: null,
            },
            // 编辑单元格每次开始编辑前的初始值
            editorInputStartValue: "",
            // 是否允许按下方向键时停止编辑并移动选中单元格
            enableStopEditing: true,
            // 上下文菜单事件目标
            contextmenuEventTarget: "",
            // 上下文菜单选项
            contextmenuOptions: [],
            // 列调整大小光标是否悬停
            isColumnResizerHover: false,
            // 是否正在调整列大小
            isColumnResizing: false,
        })

        //#region 计算属性
        const actualRenderTableData = computed(() => {
            return isVirtualScroll.value ? a.virtualScrollVisibleData : props.tableData
        })

        const allRowKeys = computed(() => {
            const { rowKeyFieldName, tableData } = props
            if (rowKeyFieldName) {
                return tableData.map(x => x[rowKeyFieldName])
            }
            return []
        })

        const virtualScrollBufferCount = computed(() => {
            if (virtualScrollOption) {
                const { bufferScale } = virtualScrollOption
                let realBufferScale =
                    isNumber(bufferScale) && bufferScale > 0 ? bufferScale : defaultVirtualScrollBufferScale
                return realBufferScale * virtualScrollVisibleCount
            }
            return 0
        })

        const virtualScrollVisibleCount = computed(() => {
            const { maxHeight } = props
            if (isVirtualScroll.value && maxHeight) {
                const minRowHeight = isNumber(virtualScrollOption.minRowHeight)
                    ? virtualScrollOption.minRowHeight
                    : defaultVirtualScrollMinRowHeight
                if (isNumber(maxHeight)) {
                    return Math.ceil(maxHeight / minRowHeight)
                } else if (tableOffestHeight) {
                    return Math.ceil(tableOffestHeight / minRowHeight)
                }
            }
            return 0
        })

        const tableContainerWrapperStyle = computed(() => ({
            width: "100%",
        }))

        // const tableContainerStyle = ref({})
        // watch(
        //   () => a.tableHeight,
        //   (newVal, oldVal) => {
        //     console.log(`watch a.tableHeight 变化 ing👇`, newVal, oldVal)
        //     let maxHeight = getValByUnit(props.maxHeight)
        //     let tableContainerHeight = a.tableHeight
        //     if (isVirtualScroll.value) {
        //       if (maxHeight) {
        //         tableContainerHeight = maxHeight
        //       } else {
        //         console.error(
        //           "maxHeight prop is required when 'virtualScrollOption.enable = true'"
        //         )
        //       }
        //     } else {
        //       // tableContainerHeight = a.tableHeight
        //       if (a.hasXScrollBar) {
        //         tableContainerHeight += getScrollBarWidth()
        //       }
        //       tableContainerHeight = getValByUnit(tableContainerHeight)
        //     }
        //     tableContainerStyle.value = {
        //       maxHeight: maxHeight,
        //       height: tableContainerHeight,
        //     }
        //     // console.log(`tableContainerStyle 👉`, tableContainerStyle.value)
        //   }
        // )

        const tableContainerStyle2 = computed(() => {
            // console.log(`tableContainerStyle2 计算 ing👇,a`, a)
            let maxHeight = getValByUnit(props.maxHeight)
            let tableContainerHeight = a.tableHeight
            if (isVirtualScroll.value) {
                if (maxHeight) {
                    tableContainerHeight = maxHeight
                } else {
                    console.error("maxHeight prop is required when 'virtualScrollOption.enable = true'")
                }
            } else {
                tableContainerHeight = a.tableHeight
                // console.log(
                //   `tableContainerStyle tableContainerHeight 👉`,
                //   tableContainerHeight
                // )
                if (a.hasXScrollBar) {
                    tableContainerHeight += getScrollBarWidth()
                }
                tableContainerHeight = getValByUnit(tableContainerHeight)
            }
            return {
                "max-height": maxHeight,
                height: tableContainerHeight,
            }
        })

        const tableStyle = computed(() => ({
            width: getValByUnit(props.scrollWidth),
        }))

        const tableClass = computed(() => ({
            [拼样式名_提前传主名("border-x")]: props.borderX,
            [拼样式名_提前传主名("border-y")]: props.borderY,
        }))

        const tableContainerClass = computed(() => {
            // amtf
            return {
                [拼样式名_提前传主名("container")]: true,
                [拼样式名_提前传主名("virtual-scroll")]: isVirtualScroll.value,
                [拼样式名_提前传主名("container-left-scrolling")]: a.isLeftScrolling,
                [拼样式名_提前传主名("container-right-scrolling")]: a.isRightScrolling,
                [拼样式名_提前传主名("container-vertical-scrolling")]: a.isVerticalScrolling,
                [拼样式名_提前传主名("is-cell-editing")]: isCellEditing.value,
                [拼样式名_提前传主名("autofilling")]: a.isAutofillStarting,
                [拼样式名_提前传主名("enable-cell-selection")]: enableCellSelection.value,
            }
        })

        const tableBodyClass = computed(() => {
            const { rowStyleOption } = props
            let hoverHighlight = true
            let clickHighlight = true
            let stripe = false
            if (rowStyleOption) {
                hoverHighlight = rowStyleOption.hoverHighlight
                clickHighlight = rowStyleOption.clickHighlight
                stripe = rowStyleOption.stripe
            }
            const kk = {
                [拼样式名_提前传主名("stripe")]: stripe === true,
                [拼样式名_提前传主名("row-hover")]: hoverHighlight !== false,
                // [拼样式名_提前传主名('row-hover')]: true,
                [拼样式名_提前传主名("row-highlight")]: clickHighlight !== false,
            }
            // console.log(`tableBodyClass kk 👉`,kk)
            return kk
        })

        const isVirtualScroll = computed(() => {
            return props.virtualScrollOption && props.virtualScrollOption.enable
        })

        const hasFixedColumn = computed(() => {
            return a.colgroups.some(x => x.fixed === COLUMN_FIXED_TYPE.LEFT || x.fixed === COLUMN_FIXED_TYPE.RIGHT)
        })

        const hasLeftFixedColumn = computed(() => {
            return a.colgroups.some(x => x.fixed === COLUMN_FIXED_TYPE.LEFT)
        })

        const hasRightFixedColumn = computed(() => {
            return a.colgroups.some(x => x.fixed === COLUMN_FIXED_TYPE.RIGHT)
        })

        const isCellEditing = computed(() => {
            // console.log(`a.editingCell 👉`, a.editingCell)
            return !isEmptyValue(a.editingCell.rowKey) && !isEmptyValue(a.editingCell.colKey)
        })

        const hasEditColumn = computed(() => {
            return a.colgroups.some(x => x.edit)
        })

        const enableHeaderContextmenu = computed(() => {
            const { contextmenuHeaderOption } = props
            if (contextmenuHeaderOption) {
                const { contextmenus } = contextmenuHeaderOption
                return Array.isArray(contextmenus) && contextmenus.length
            }
            return false
        })

        const enableBodyContextmenu = computed(() => {
            const { contextmenuBodyOption } = props
            if (contextmenuBodyOption) {
                const { contextmenus } = contextmenuBodyOption
                return Array.isArray(contextmenus) && contextmenus.length
            }
            return false
        })

        const contextMenuType = computed(() => {
            if (a.headerIndicatorColKeys.startColKeyIndex > -1) {
                return CONTEXTMENU_TYPES.HEADER_CONTEXTMENU
            } else {
                return CONTEXTMENU_TYPES.BODY_CONTEXTMENU
            }
        })

        const enableCellSelection = computed(() => {
            const { rowKeyFieldName, cellSelectionOption } = props
            // console.log(`enableCellSelection rowKeyFieldName 👉`, rowKeyFieldName)
            if (isEmptyValue(rowKeyFieldName)) {
                return false
            } else if (
                cellSelectionOption &&
                isBoolean(cellSelectionOption.enable) &&
                cellSelectionOption.enable === false
            ) {
                return false
            }
            return true
        })

        const enableClipboard = computed(() => {
            return props.rowKeyFieldName
        })

        const enableColumnResize = computed(() => {
            // console.log(`enableColumnResize 计算 ing👇`)
            const { columnWidthResizeOption } = props
            if (columnWidthResizeOption) {
                const { enable } = columnWidthResizeOption
                return isBoolean(enable) && enable
            }
            return false
        })

        const headerTotalHeight = computed(() => {
            if (props.showHeader) {
                return a.headerRows.reduce((total, currentVal) => currentVal.rowHeight + total, 0)
            }
            return 0
        })

        const footerTotalHeight = computed(() => {
            return a.footerRows.reduce((total, currentVal) => currentVal.rowHeight + total, 0)
        })
        //#endregion

        //#region 方法
        const initHeaderRows = () => {
            if (Array.isArray(a.groupColumns)) {
                a.headerRows = a.groupColumns.map(() => ({ rowHeight: 0 }))
            }
        }

        const initFooterRows = () => {
            // console.log(`props.footerData 👉`, props.footerData)
            if (Array.isArray(props.footerData)) {
                a.footerRows = props.footerData.map(() => ({ rowHeight: 0 }))
            }
            // console.log(`a.footerRows 👉`, a.footerRows)
        }

        const headerRowHeightChange = ({ rowIndex, height }) => {
            a.headerRows.splice(rowIndex, 1, { rowHeight: height })
        }

        const footRowHeightChange = ({ rowIndex, height }) => {
            // console.log(`footRowHeightChange ing👇`)
            // vue2替换元素并且保持响应式的做法👇
            a.footerRows.splice(rowIndex, 1, { rowHeight: height })
            // a.footerRows[rowIndex]= { rowHeight: height }
        }

        const bodyCellWidthChange = colWidths => {
            // console.log(`bodyCellWidthChange ing👇`)
            // console.log(`bodyCellWidthChange 👉`, colWidths)
            a.colgroups = a.colgroups.map(item => {
                item._realTimeWidth = colWidths.get(item.key)
                return item
            })

            triggerHook(HOOKS_NAME.TABLE_CELL_WIDTH_CHANGE)
        }

        const setColumnWidth = ({ colKey, width }) => {
            a.colgroups = a.colgroups.map((item, index) => {
                // console.log(`item 👉`, item)
                // if (index == 1) {
                //   console.log(`item 👉`, item)
                // }
                if (item.key === colKey) {
                    item._columnResizeWidth = width
                }
                return item
            })
            nextTick(() => {
                setScrollBarStatus()
            })
            triggerHook(HOOKS_NAME.TABLE_CELL_WIDTH_CHANGE)
        }

        const updateColgroupsBySortChange = sortColumns => {
            a.colgroups = a.colgroups.map(item => {
                // update a.colgroups by sort columns
                if (Object.keys(sortColumns).indexOf(item.field) > -1) {
                    item.sortBy = sortColumns[item.field]
                }
                return item
            })
        }

        const initColumnWidthByColumnResize = () => {
            // console.log(`initColumnWidthByColumnResize ing👇`)
            const columnDefaultWidth = 50
            if (enableColumnResize.value) {
                a.colgroups = a.colgroups.map(item => {
                    // console.log(`item 👉`, item)
                    let columnWidth = columnDefaultWidth
                    if (isNumber(item.width)) {
                        columnWidth = item.width
                    }
                    item._columnResizeWidth = columnWidth
                    return item
                })
            }
        }

        const initColumns = () => {
            const { columnHiddenOption } = props
            if (columnHiddenOption) {
                const { defaultHiddenColumnKeys } = columnHiddenOption
                if (defaultHiddenColumnKeys && defaultHiddenColumnKeys.length > 0) {
                    a.a.hiddenColumns = defaultHiddenColumnKeys
                }
            }
            showOrHideColumns()
        }

        const showOrHideColumns = () => {
            let cloneColumns = util.深拷贝(props.columns)
            // console.log(`showOrHideColumns cloneColumns 👉`, cloneColumns)
            cloneColumns = cloneColumns.map(col => {
                // 操作列默认左固定
                if (col.operationColumn) {
                    col.fixed = COLUMN_FIXED_TYPE.LEFT
                }
                return col
            })

            if (a.hiddenColumns && a.hiddenColumns.length > 0) {
                //  recursive remove column key
                a.hiddenColumns.forEach(key => {
                    cloneColumns = recursiveRemoveColumnByKey(cloneColumns, key)
                })
            }
            a.cloneColumns = cloneColumns
        }

        const initGroupColumns = () => {
            // console.log(
            //   `initGroupColumnsFn a.cloneColumns 👉`,
            //   a.cloneColumns
            // )
            const result = util_initGroupColumns(a.cloneColumns)
            a.isGroupHeader = result.isGroupHeader
            a.colgroups = result.colgroups
            // console.log(`a.colgroups 👉`, a.colgroups)
            a.groupColumns = result.groupColumns
        }

        const getScrollBarWidth = () => {
            let result = 0
            if (a.scrollBarWidth) {
                result = a.scrollBarWidth
            } else {
                result = getScrollbarWidth()
                a.scrollBarWidth = result
            }
            return result
        }

        const selectedAllChange = ({ isSelected }) => {
            broadcast(COMPS_NAME.VE_TABLE_BODY, EMIT_EVENTS.CHECKBOX_SELECTED_ALL_CHANGE, {
                isSelected,
            })
        }

        const setSelectedAllInfo = ({ isSelected, isIndeterminate }) => {
            broadcast(COMPS_NAME.VE_TABLE_HEADER_CHECKBOX_CONTENT, EMIT_EVENTS.CHECKBOX_SELECTED_ALL_INFO, {
                isSelected,
                isIndeterminate,
            })
        }

        const 改变选中单元格 = ({ rowKey, colKey }) => {
            // console.log(`改变选中单元格 ing👇`)
            a.cellSelectionData.currentCell.colKey = colKey
            a.cellSelectionData.currentCell.rowKey = rowKey
            a.cellSelectionData.currentCell.rowIndex = allRowKeys.value.indexOf(rowKey)
        }

        const cellSelectionNormalEndCellChange = ({ rowKey, colKey }) => {
            console.log(`cellSelectionNormalEndCellChange ing👇`)
            a.cellSelectionData.normalEndCell.colKey = colKey
            a.cellSelectionData.normalEndCell.rowKey = rowKey
            a.cellSelectionData.normalEndCell.rowIndex = allRowKeys.value.indexOf(rowKey)
        }

        const cellSelectionAutofillCellChange = ({ rowKey, colKey }) => {
            a.cellSelectionData.autoFillEndCell.colKey = colKey
            a.cellSelectionData.autoFillEndCell.rowKey = rowKey
        }

        const clearCellSelectionCurrentCell = () => {
            改变选中单元格({
                rowKey: "",
                colKey: "",
                rowIndex: -1,
            })
        }

        const clearCellSelectionNormalEndCell = () => {
            cellSelectionNormalEndCellChange({
                rowKey: "",
                colKey: "",
                rowIndex: -1,
            })
        }

        const clearCellSelectionAutofillEndCell = () => {
            cellSelectionAutofillCellChange({ rowKey: "", colKey: "" })
        }

        const headerIndicatorColKeysChange = ({ startColKey, endColKey }) => {
            const startColKeyIndex = a.colgroups.findIndex(x => x.key === startColKey)
            const endColKeyIndex = a.colgroups.findIndex(x => x.key === endColKey)
            a.headerIndicatorColKeys.startColKey = startColKey
            a.headerIndicatorColKeys.startColKeyIndex = startColKeyIndex
            a.headerIndicatorColKeys.endColKey = endColKey
            a.headerIndicatorColKeys.endColKeyIndex = endColKeyIndex
        }

        const clearHeaderIndicatorColKeys = () => {
            a.headerIndicatorColKeys.startColKey = ""
            a.headerIndicatorColKeys.startColKeyIndex = -1
            a.headerIndicatorColKeys.endColKey = ""
            a.headerIndicatorColKeys.endColKeyIndex = -1
        }

        const bodyIndicatorRowKeysChange = ({ startRowKey, endRowKey }) => {
            const startRowKeyIndex = allRowKeys.value.indexOf(startRowKey)
            const endRowKeyIndex = allRowKeys.value.indexOf(endRowKey)
            a.bodyIndicatorRowKeys.startRowKey = startRowKey
            a.bodyIndicatorRowKeys.startRowKeyIndex = startRowKeyIndex
            a.bodyIndicatorRowKeys.endRowKey = endRowKey
            a.bodyIndicatorRowKeys.endRowKeyIndex = endRowKeyIndex
        }

        const clearBodyIndicatorRowKeys = () => {
            a.bodyIndicatorRowKeys.startRowKey = ""
            a.bodyIndicatorRowKeys.startRowKeyIndex = -1
            a.bodyIndicatorRowKeys.endRowKey = ""
            a.bodyIndicatorRowKeys.endRowKeyIndex = -1
        }

        const 设置选中区域ByAutofill = () => {
            const { rowKeyFieldName, tableData, cellAutofillOption } = props
            const { autoFillEndCell, currentCell } = a.cellSelectionData
            const { rowKey, colKey } = autoFillEndCell
            if (isEmptyValue(rowKey) || isEmptyValue(colKey)) {
                return false
            }
            let currentCellData = {}
            let normalEndCellData = {}
            const { leftColKey, rightColKey, topRowKey, bottomRowKey } = a.cellSelectionRangeData
            // cell selection range auto fill
            if (a.currentCellSelectionType === CURRENT_CELL_SELECTION_TYPES.RANGE) {
                if (
                    !isCellInSelectionRange({
                        cellData: autoFillEndCell,
                        cellSelectionRangeData: a.cellSelectionRangeData,
                        colgroups: a.colgroups,
                        allRowKeys: allRowKeys.value,
                    })
                ) {
                    if (autofillingDirection === AUTOFILLING_DIRECTION.RIGHT) {
                        currentCellData = {
                            rowKey: topRowKey,
                            colKey: leftColKey,
                        }
                        normalEndCellData = { rowKey: bottomRowKey, colKey }
                    } else if (autofillingDirection === AUTOFILLING_DIRECTION.DOWN) {
                        currentCellData = {
                            rowKey: topRowKey,
                            colKey: leftColKey,
                        }
                        normalEndCellData = { rowKey, colKey: rightColKey }
                    } else if (autofillingDirection === AUTOFILLING_DIRECTION.UP) {
                        currentCellData = {
                            rowKey,
                            colKey: leftColKey,
                        }
                        normalEndCellData = {
                            rowKey: bottomRowKey,
                            colKey: rightColKey,
                        }
                    } else if (autofillingDirection === AUTOFILLING_DIRECTION.LEFT) {
                        currentCellData = { rowKey: topRowKey, colKey }
                        normalEndCellData = {
                            rowKey: bottomRowKey,
                            colKey: rightColKey,
                        }
                    }
                } else {
                    // return if within the range
                    return false
                }
            }
            // cell selection single auto fill
            else if (a.currentCellSelectionType === CURRENT_CELL_SELECTION_TYPES.SINGLE) {
                if (currentCell.rowKey !== rowKey || currentCell.colKey !== colKey) {
                    if (autofillingDirection === AUTOFILLING_DIRECTION.RIGHT) {
                        currentCellData = {
                            rowKey,
                            colKey: leftColKey,
                        }
                        normalEndCellData = {
                            rowKey,
                            colKey,
                        }
                    } else if (autofillingDirection === AUTOFILLING_DIRECTION.DOWN) {
                        currentCellData = {
                            rowKey: topRowKey,
                            colKey: leftColKey,
                        }
                        normalEndCellData = {
                            rowKey,
                            colKey: leftColKey,
                        }
                    } else if (autofillingDirection === AUTOFILLING_DIRECTION.UP) {
                        currentCellData = {
                            rowKey,
                            colKey: leftColKey,
                        }
                        normalEndCellData = {
                            rowKey: bottomRowKey,
                            colKey: leftColKey,
                        }
                    } else if (autofillingDirection === AUTOFILLING_DIRECTION.LEFT) {
                        currentCellData = {
                            rowKey,
                            colKey,
                        }
                        normalEndCellData = {
                            rowKey,
                            colKey: rightColKey,
                        }
                    }
                } else {
                    // return if within the range
                    return false
                }
            }

            const cellAutofillParams = {
                tableData: tableData,
                allRowKeys: allRowKeys.value,
                colgroups: a.colgroups,
                rowKeyFieldName: rowKeyFieldName,
                direction: autofillingDirection,
                currentCellSelectionType: a.currentCellSelectionType,
                cellSelectionRangeData: a.cellSelectionRangeData,
                nextCurrentCell: currentCellData,
                nextNormalEndCell: normalEndCellData,
            }

            if (cellAutofillOption) {
                const { beforeAutofill, afterAutofill } = cellAutofillOption

                if (isFunction(beforeAutofill)) {
                    // before autofill
                    const autofillResponse = cellAutofill({
                        isReplaceData: false,
                        ...cellAutofillParams,
                    })
                    const callback = beforeAutofill(autofillResponse)
                    if (isBoolean(callback) && !callback) {
                        return false
                    }
                }

                // after autofill
                const autofillResponse = cellAutofill({
                    isReplaceData: true,
                    ...cellAutofillParams,
                })
                if (isFunction(afterAutofill)) {
                    afterAutofill(autofillResponse)
                }
            }

            if (!isEmptyValue(currentCellData.rowKey)) {
                改变选中单元格({
                    rowKey: currentCellData.rowKey,
                    colKey: currentCellData.colKey,
                })
            }

            if (!isEmptyValue(normalEndCellData.rowKey)) {
                cellSelectionNormalEndCellChange({
                    rowKey: normalEndCellData.rowKey,
                    colKey: normalEndCellData.colKey,
                })
            }
        }

        const cellSelectionRangeDataChange = newData => {
            a.cellSelectionRangeData = {
                ...a.cellSelectionRangeData,
                ...newData,
            }
        }

        const autofillingDirectionChange = direction => {
            a.autofillingDirection = direction
        }

        const setCurrentCellSelectionType = () => {
            const { currentCell, normalEndCell } = a.cellSelectionData

            let result

            if (isEmptyValue(currentCell.rowKey) || isEmptyValue(currentCell.colKey)) {
                result = ""
            } else {
                if (!isEmptyValue(normalEndCell.rowKey) && !isEmptyValue(normalEndCell.colKey)) {
                    result = CURRENT_CELL_SELECTION_TYPES.RANGE
                } else {
                    result = CURRENT_CELL_SELECTION_TYPES.SINGLE
                }
            }

            a.currentCellSelectionType = result
        }

        const dealKeydownEvent = event => {
            const { keyCode, ctrlKey, shiftKey, altKey } = event
            const { rowKey, colKey } = a.cellSelectionData.currentCell
            const currentColumn = a.colgroups.find(x => x.key === colKey)
            if (rowKey && colKey) {
                switch (keyCode) {
                    case KEY_CODES.TAB: {
                        let direction
                        if (shiftKey) {
                            direction = CELL_SELECTION_DIRECTION.LEFT
                        } else {
                            direction = CELL_SELECTION_DIRECTION.RIGHT
                        }

                        selectCellByDirection({ direction })

                        clearCellSelectionNormalEndCell()

                        停止编辑单元格()
                        event.preventDefault()
                        break
                    }
                    case KEY_CODES.ARROW_LEFT: {
                        const direction = CELL_SELECTION_DIRECTION.LEFT
                        if (enableStopEditing) {
                            selectCellByDirection({ direction })

                            clearCellSelectionNormalEndCell()

                            停止编辑单元格()
                            event.preventDefault()
                        }
                        break
                    }
                    case KEY_CODES.ARROW_RIGHT: {
                        const direction = CELL_SELECTION_DIRECTION.RIGHT

                        if (enableStopEditing) {
                            selectCellByDirection({ direction })

                            clearCellSelectionNormalEndCell()

                            停止编辑单元格()
                            event.preventDefault()
                        }
                        break
                    }
                    case KEY_CODES.ARROW_UP: {
                        const direction = CELL_SELECTION_DIRECTION.UP

                        if (enableStopEditing) {
                            selectCellByDirection({ direction })

                            clearCellSelectionNormalEndCell()

                            停止编辑单元格()
                            event.preventDefault()
                        }
                        break
                    }
                    case KEY_CODES.ARROW_DOWN: {
                        const direction = CELL_SELECTION_DIRECTION.DOWN

                        if (a.enableStopEditing) {
                            selectCellByDirection({ direction })
                            clearCellSelectionNormalEndCell()
                            停止编辑单元格()
                            event.preventDefault()
                        }
                        break
                    }
                    case KEY_CODES.ENTER: {
                        let direction
                        // add new line
                        if (altKey) {
                            const editInputEditor = instance.proxy.$refs[a.editInputRef]
                            // 假设editInputEditor存在textareaAddNewLine方法
                            editInputEditor.textareaAddNewLine()
                        }
                        // direction up
                        else if (shiftKey) {
                            direction = CELL_SELECTION_DIRECTION.UP
                            停止编辑单元格()
                        }
                        // stop editing and stay in current cell
                        else if (ctrlKey) {
                            停止编辑单元格()
                        }
                        // direction down
                        else {
                            direction = CELL_SELECTION_DIRECTION.DOWN
                            停止编辑单元格()
                        }

                        if (direction) {
                            clearCellSelectionNormalEndCell()
                            selectCellByDirection({ direction })
                        }
                        event.preventDefault()
                        break
                    }
                    case KEY_CODES.SPACE: {
                        if (!isCellEditing.value) {
                            // 假设START_EDITING_CELL方法已经在合适的地方定义并可访问
                            编辑单元格({
                                rowKey,
                                colKey,
                                defaultValue: " ",
                            })
                            event.preventDefault()
                        }
                        break
                    }
                    case KEY_CODES.BACK_SPACE: {
                        if (!isCellEditing.value) {
                            编辑单元格({
                                rowKey,
                                colKey,
                                defaultValue: "",
                            })
                            event.preventDefault()
                        }
                        break
                    }
                    case KEY_CODES.DELETE: {
                        if (!isCellEditing.value) {
                            // 假设deleteCellSelectionRangeValue方法已经在合适的地方定义并可访问
                            deleteCellSelectionRangeValue()
                            event.preventDefault()
                        }
                        break
                    }
                    case KEY_CODES.F2: {
                        if (!isCellEditing.value) {
                            if (currentColumn.edit) {
                                // 假设enableStopEditing可直接修改
                                a.enableStopEditing = false
                                编辑单元格({
                                    rowKey,
                                    colKey,
                                })
                            }
                            event.preventDefault()
                        }
                        break
                    }
                    default: {
                        // enter text directly
                        if (isInputKeyCode(event)) {
                            编辑单元格({
                                rowKey,
                                colKey,
                                defaultValue: "",
                            })
                        }
                        break
                    }
                }
            }
        }

        const selectCellByDirection = ({ direction }) => {
            const { rowKey, colKey } = a.cellSelectionData.currentCell
            let columnIndex = a.colgroups.findIndex(x => x.key === colKey)
            let rowIndex = allRowKeys.value.indexOf(rowKey)

            if (direction === CELL_SELECTION_DIRECTION.LEFT) {
                if (columnIndex > 0) {
                    let nextColumn = a.colgroups[columnIndex - 1]
                    a.cellSelectionData.currentCell.colKey = nextColumn.key
                    columnToVisible(nextColumn)
                }
            } else if (direction === CELL_SELECTION_DIRECTION.RIGHT) {
                if (columnIndex < a.colgroups.length - 1) {
                    let nextColumn = a.colgroups[columnIndex + 1]
                    a.cellSelectionData.currentCell.colKey = nextColumn.key
                    columnToVisible(nextColumn)
                }
            } else if (direction === CELL_SELECTION_DIRECTION.UP) {
                if (rowIndex > 0) {
                    const nextRowKey = allRowKeys.value[rowIndex - 1]
                    rowToVisible(KEY_CODES.ARROW_UP, nextRowKey)
                }
            } else if (direction === CELL_SELECTION_DIRECTION.DOWN) {
                if (rowIndex < allRowKeys.value.length - 1) {
                    const nextRowKey = allRowKeys.value[rowIndex + 1]
                    rowToVisible(KEY_CODES.ARROW_DOWN, nextRowKey)
                }
            }
        }

        const columnToVisible = nextColumn => {
            if (!a.hasXScrollBar) {
                return false
            }

            const tableContainerRef = instance.proxy.$refs[a.tableContainerRef]

            const { scrollWidth, clientWidth, scrollLeft } = tableContainerRef

            if (!nextColumn.fixed) {
                const leftTotalWidth = getNotFixedTotalWidthByColumnKey({
                    colgroups: a.colgroups,
                    colKey: nextColumn.key,
                    fixed: COLUMN_FIXED_TYPE.LEFT,
                })

                const rightTotalWidth = getNotFixedTotalWidthByColumnKey({
                    colgroups: a.colgroups,
                    colKey: nextColumn.key,
                    fixed: COLUMN_FIXED_TYPE.RIGHT,
                })

                if (scrollLeft) {
                    const diff = scrollLeft - leftTotalWidth
                    if (diff > 0) {
                        tableContainerRef.scrollLeft = scrollLeft - diff
                    }
                }

                const scrollRight = scrollWidth - clientWidth - scrollLeft
                if (scrollRight) {
                    const diff = scrollRight - rightTotalWidth
                    if (diff > 0) {
                        tableContainerRef.scrollLeft = scrollLeft + diff
                    }
                }
            }
        }

        const rowToVisible = (keyCode, nextRowKey) => {
            const tableContainerRef = instance.proxy.$refs[a.tableContainerRef]
            // console.log(`tableContainerRef 👉`, tableContainerRef)
            let kk = instance.proxy.$refs[a.tableContentWrapperRef]
            // console.log(`kk 👉`, kk)
            const tableContentWrapperRef =
                // a.$refs[a.tableContentWrapperRef].$el
                // instance.proxy.$refs[a.tableContentWrapperRef].__vnode.el
                instance.proxy.$refs[a.tableContentWrapperRef].$el

            const { clientHeight: containerClientHeight, scrollTop: containerScrollTop } = tableContainerRef

            const nextRowEl = instance.proxy.$el.querySelector(
                `tbody tr[${COMPS_CUSTOM_ATTRS.BODY_ROW_KEY}="${nextRowKey}"]`
            )

            if (nextRowEl) {
                const { offsetTop: trOffsetTop, clientHeight: trClientHeight } = nextRowEl

                const parentOffsetTop = tableContentWrapperRef.offsetTop

                // arrow up
                if (keyCode === KEY_CODES.ARROW_UP) {
                    let diff = 0
                    if (isVirtualScroll.value) {
                        diff = headerTotalHeight.value - (trOffsetTop - (containerScrollTop - parentOffsetTop))
                    } else {
                        diff = containerScrollTop + headerTotalHeight.value - trOffsetTop
                    }

                    if (diff > 0) {
                        tableContainerRef.scrollTop = containerScrollTop - diff
                    }
                }
                // arrow down
                else if (keyCode === KEY_CODES.ARROW_DOWN) {
                    let diff = 0
                    if (isVirtualScroll.value) {
                        diff =
                            trOffsetTop -
                            (containerScrollTop - parentOffsetTop) +
                            trClientHeight +
                            footerTotalHeight.value -
                            containerClientHeight
                    } else {
                        diff =
                            trOffsetTop +
                            trClientHeight +
                            footerTotalHeight.value -
                            (containerClientHeight + containerScrollTop)
                    }

                    if (diff >= 0) {
                        tableContainerRef.scrollTop = containerScrollTop + diff
                    }
                }
                const { currentCell } = a.cellSelectionData
                改变选中单元格({
                    rowKey: nextRowKey,
                    colKey: currentCell.colKey,
                })
            }
        }

        const setVirtualScrollVisibleData = () => {
            const startIndex = a.virtualScrollStartIndex
            const endIndex = a.virtualScrollEndIndex
            const aboveCount = getVirtualScrollAboveCount()
            const belowCount = a.getVirtualScrollBelowCount()
            let start = startIndex - aboveCount
            let end = endIndex + belowCount
            a.virtualScrollVisibleIndexs.start = start
            a.virtualScrollVisibleIndexs.end = end - 1
            a.virtualScrollVisibleData = props.tableData.slice(start, end)
        }

        const getVirtualScrollAboveCount = () => {
            let result = 0

            const virtualScrollStartIndex = a.virtualScrollStartIndex

            if (isVirtualScroll.value) {
                result = Math.min(virtualScrollStartIndex, virtualScrollBufferCount.value)
            }
            return result
        }

        const getVirtualScrollBelowCount = () => {
            let result = 0
            const virtualScrollEndIndex = a.virtualScrollEndIndex
            if (isVirtualScroll.value) {
                result = Math.min(props.tableData.length - virtualScrollEndIndex, a.virtualScrollBufferCount.value)
            }
            return result
        }

        const getVirtualViewPhantom = () => {
            // console.log(`getVirtualViewPhantom ing👇`)
            let content = null
            // 1、is virtualScroll
            // or
            // 2、
            // has left fixed column and expand option（resolve expand row content sticky）
            if (isVirtualScroll.value || (hasLeftFixedColumn.value && props.expandOption)) {
                const resizeObserverProps = {
                    tagName: "div",
                    style: {
                        width: "100%",
                    },
                    onDomResizeChange: ({ width }) => {
                        a.tableViewportWidth = width
                    },
                }

                content = h(
                    "div",
                    {
                        ref: a.virtualPhantomRef,
                        class: [
                            拼样式名_提前传主名("virtual-phantom"),
                            isVirtualScroll.value ? 拼样式名_提前传主名("virtual-scroll") : "",
                        ],
                    },
                    [h(VueDomResizeObserver, resizeObserverProps)]
                )
            }
            // console.log(`content 👉`, content)
            return content
        }

        const initVirtualScrollPositions = () => {
            const { rowKeyFieldName, virtualScrollOption, tableData } = props
            if (isVirtualScroll.value) {
                const minRowHeight = isNumber(virtualScrollOption.minRowHeight)
                    ? virtualScrollOption.minRowHeight
                    : a.defaultVirtualScrollMinRowHeight
                a.virtualScrollPositions = tableData.map((item, index) => ({
                    rowKey: item[rowKeyFieldName],
                    height: minRowHeight,
                    top: index * minRowHeight,
                    bottom: (index + 1) * minRowHeight,
                }))
            }
        }

        const bodyRowHeightChange = ({ rowKey, height }) => {
            // 获取真实元素大小，修改对应的尺寸缓存
            const index = a.virtualScrollPositions.findIndex(x => x.rowKey === rowKey)
            let oldHeight = a.virtualScrollPositions[index].height
            let dValue = oldHeight - height
            // 存在差值
            if (dValue) {
                a.virtualScrollPositions[index].bottom = a.virtualScrollPositions[index].bottom - dValue
                a.virtualScrollPositions[index].height = height
                for (let k = index + 1; k < a.virtualScrollPositions.length; k++) {
                    a.virtualScrollPositions[k].top = a.virtualScrollPositions[k - 1].bottom
                    a.virtualScrollPositions[k].bottom = a.virtualScrollPositions[k].bottom - dValue
                }

                // 更新 virtual phantom 列表总高度
                setVirtualPhantomHeight()

                // 更新真实偏移量
                setVirtualScrollStartOffset()
            }
        }

        const setVirtualPhantomHeight = () => {
            let totalHeight = 0
            if (a.virtualScrollPositions.length) {
                totalHeight = a.virtualScrollPositions[a.virtualScrollPositions.length - 1].bottom
            }
            instance.proxy.$refs[a.virtualPhantomRef].style.height = totalHeight + "px"
        }

        const setVirtualScrollStartOffset = () => {
            const start = a.virtualScrollStartIndex
            const aboveCount = getVirtualScrollAboveCount()
            let startOffset = 0
            if (start >= 1) {
                let size =
                    a.virtualScrollPositions[start].top -
                    (a.virtualScrollPositions[start - aboveCount]
                        ? a.virtualScrollPositions[start - aboveCount].top
                        : 0)
                startOffset = a.virtualScrollPositions[start - 1].bottom - size
            }
            setTableContentTopValue({ top: startOffset })
        }

        const setTableContentTopValue = ({ top }) => {
            window.requestAnimationFrame(() => {
                const ele = instance.proxy.$refs[a.tableContentWrapperRef]
                if (ele) {
                    ele.$el.style.top = `${top}px`
                }
            })
        }

        const getVirtualScrollStartIndex = (scrollTop = 0) => {
            return virtualScrollBinarySearch(a.virtualScrollPositions, scrollTop)
        }

        const virtualScrollBinarySearch = (list, value) => {
            let start = 0
            let end = list.length - 1
            let tempIndex = null

            while (start <= end) {
                let midIndex = parseInt((start + end) / 2)
                let midValue = list[midIndex].bottom
                if (midValue === value) {
                    return midIndex + 1
                } else if (midValue < value) {
                    start = midIndex + 1
                } else if (midValue > value) {
                    if (tempIndex === null || tempIndex > midIndex) {
                        tempIndex = midIndex
                    }
                    end = end - 1
                }
            }
            return tempIndex
        }

        const tableContainerVirtualScrollHandler = tableContainerRef => {
            const { virtualScrollVisibleCount: visibleCount, virtualScrollOption } = a

            // 当前滚动位置
            let scrollTop = tableContainerRef.scrollTop

            // 此时的开始索引
            let visibleStartIndex = getVirtualScrollStartIndex(scrollTop)
            a.virtualScrollStartIndex = visibleStartIndex

            // 此时的结束索引
            let visibleEndIndex = visibleStartIndex + visibleCount
            a.virtualScrollEndIndex = visibleEndIndex

            const visibleAboveCount = getVirtualScrollAboveCount()
            const visibleBelowCount = getVirtualScrollBelowCount()

            // 此时的偏移量
            setVirtualScrollStartOffset()

            if (!a.showVirtualScrollingPlaceholder) {
                const bodyElement = instance.proxy.$refs[a.tableBodyRef]

                if (bodyElement) {
                    bodyElement.renderingRowKeys(
                        allRowKeys.value.slice(
                            visibleStartIndex - visibleAboveCount,
                            visibleEndIndex + visibleBelowCount
                        )
                    )
                }
            }

            const { scrolling } = virtualScrollOption
            if (isFunction(scrolling)) {
                const visibleAboveCount = getVirtualScrollAboveCount()
                const visibleBelowCount = getVirtualScrollBelowCount()

                let startRowIndex = visibleStartIndex - visibleAboveCount

                scrolling({
                    startRowIndex: startRowIndex > 0 ? startRowIndex : 0,
                    visibleStartIndex,
                    visibleEndIndex,
                    visibleAboveCount,
                    visibleBelowCount,
                })
            }

            setVirtualScrollVisibleData()
        }

        const debounceScrollEnded = () => {
            const scrollingResetTimeInterval = 150

            if (disablePointerEventsTimeoutId) {
                cancelAnimationTimeout(disablePointerEventsTimeoutId)
            }

            a.disablePointerEventsTimeoutId = requestAnimationTimeout(
                debounceScrollEndedCallback,
                scrollingResetTimeInterval
            )
        }

        const debounceScrollEndedCallback = () => {
            a.disablePointerEventsTimeoutId = null
            a.showVirtualScrollingPlaceholder = false
        }

        const initVirtualScroll = () => {
            if (isVirtualScroll.value) {
                const startIndex = 0

                a.virtualScrollStartIndex = startIndex
                a.virtualScrollEndIndex = startIndex + a.virtualScrollVisibleCount

                // 修复渲染结束，同时开启虚拟滚动和设置表格数据，无法设置 virtual phantom 高度的问题
                onMounted(() => {
                    const tableContainerRef = instance.proxy.$refs[a.tableContainerRef]
                    tableContainerVirtualScrollHandler(tableContainerRef)
                    setVirtualPhantomHeight()
                })
            }
        }

        const setScrolling = tableContainerRef => {
            if (a.hasFixedColumn) {
                const { scrollWidth, clientWidth, scrollLeft } = tableContainerRef
                const previewScrollLeft = previewTableContainerScrollLeft

                // 仅横向滚动需要处理
                if (previewScrollLeft === 0 || previewScrollLeft !== scrollLeft) {
                    a.previewTableContainerScrollLeft = scrollLeft

                    a.a.isLeftScrolling = scrollLeft > 0
                    a.a.isRightScrolling = scrollWidth - clientWidth > scrollLeft
                }
                a.a.isLeftScrolling = scrollLeft > 0
                a.a.isRightScrolling = scrollWidth - clientWidth > scrollLeft
            }

            if (a.fixedHeader) {
                const { scrollTop } = tableContainerRef
                a.a.isVerticalScrolling = scrollTop > 0
            }
        }

        const setScrollBarStatus = () => {
            const tableContainerRef = instance.proxy.$refs[a.tableContainerRef]
            if (tableContainerRef) {
                const { scrollWidth, clientWidth, scrollHeight, clientHeight } = tableContainerRef

                if (scrollWidth && clientWidth) {
                    a.hasXScrollBar = scrollWidth - clientWidth ? true : false
                }

                if (scrollHeight && clientHeight) {
                    a.hasYScrollBar = scrollHeight - clientHeight ? true : false
                }
            }
        }

        const initScrolling = () => {
            setScrolling(instance.proxy.$refs[a.tableContainerRef])
        }

        const tableClickOutside = e => {
            // 排除点击上下文菜单面板
            if (isContextmenuPanelClicked(e)) return false

            a.isHeaderCellMousedown = false
            // console.log(`取消 isBodyCellMousedown  ing👇`)
            a.isBodyCellMousedown = false
            a.isBodyOperationColumnMousedown = false
            a.isAutofillStarting = false
            setIsColumnResizing(false)

            // 清除单元格选择
            clearCellSelectionCurrentCell()
            clearCellSelectionNormalEndCell()

            // 清除指示器
            clearHeaderIndicatorColKeys()
            clearBodyIndicatorRowKeys()

            停止编辑单元格()
        }

        const 保存单元格 = () => {
            console.log(`保存单元格 ing👇`)
            const { editOption, tableData, rowKeyFieldName } = props
            const { cellValueChange, beforeCellValueChange, afterCellValueChange } = editOption
            if (isCellEditing.value) {
                const { rowKey, colKey } = a.editingCell
                let currentRow = tableData.find(x => x[rowKeyFieldName] === rowKey)
                if (currentRow) {
                    const currentColumn = a.colgroups.find(x => x.key === colKey)
                    const changeValue = a.editingCell.row[currentColumn.field]
                    if (isFunction(beforeCellValueChange)) {
                        const allowChange = beforeCellValueChange({
                            row: util.深拷贝(currentRow),
                            column: currentColumn,
                            changeValue,
                        })
                        if (isBoolean(allowChange) && !allowChange) {
                            // celar editing cell
                            删单元格()
                            return false
                        }
                    }
                    currentRow[currentColumn.field] = changeValue

                    // 同 afterCellValueChange，未来被移除
                    cellValueChange &&
                        cellValueChange({
                            row: currentRow,
                            column: currentColumn,
                            changeValue,
                        })

                    afterCellValueChange &&
                        afterCellValueChange({
                            row: currentRow,
                            column: currentColumn,
                            changeValue,
                        })

                    // celar editing cell
                    删单元格()
                }

                // reset status
                a.enableStopEditing = true
            }
        }

        const cellSelectionByClick = ({ rowData, column }) => {
            // console.log(`cellSelectionByClick ing👇`)
            const { rowKeyFieldName } = props
            const rowKey = getRowKey(rowData, rowKeyFieldName)
            // set cell selection and column to visible
            设置选中区域({
                rowKey,
                colKey: column.key,
                isScrollToRow: false,
            })
            // row to visible
            rowToVisible(KEY_CODES.ARROW_UP, rowKey)
            rowToVisible(KEY_CODES.ARROW_DOWN, rowKey)
        }

        const bodyCellContextmenu = ({ event, rowData, column }) => {
            const { editOption, rowKeyFieldName } = props
            if (editOption) {
                const rowKey = getRowKey(rowData, rowKeyFieldName)
                编辑单元格ByClick({
                    isDblclick: false,
                    rowKey,
                    colKey: column.key,
                })
            }

            setContextmenuOptions(column)
        }

        const 双击单元格 = ({ event, rowData, column }) => {
            const { editOption, rowKeyFieldName } = props
            if (isOperationColumn(column.key, a.colgroups)) {
                // clear cell selection
                clearCellSelectionCurrentCell()
                clearCellSelectionNormalEndCell()
                // stop editing cell
                停止编辑单元格()
                return false
            }
            if (editOption) {
                const rowKey = getRowKey(rowData, rowKeyFieldName)
                编辑单元格ByClick({
                    isDblclick: true,
                    rowKey,
                    colKey: column.key,
                })
            }
        }

        const bodyCellClick = ({ event, rowData, column }) => {
            // feature...
        }

        const 单元格鼠标按下 = ({ event, rowData, column }) => {
            // console.log(`单元格鼠标按下 ing👇`)
            const { rowKeyFieldName, editOption } = props

            if (!enableCellSelection.value) return false
            const { shiftKey } = event
            const rowKey = getRowKey(rowData, rowKeyFieldName)
            const colKey = column.key
            const { currentCell } = a.cellSelectionData
            const mouseEventClickType = getMouseEventClickType(event)
            if (isOperationColumn(colKey, a.colgroups)) {
                // clear header indicator colKeys
                clearHeaderIndicatorColKeys()

                a.isBodyOperationColumnMousedown = true

                const { startRowKey, endRowKey, startRowKeyIndex, endRowKeyIndex } = a.bodyIndicatorRowKeys
                let newStartRowKey = startRowKey
                let newEndRowKey = endRowKey

                if (shiftKey && (startRowKeyIndex > -1 || currentCell.rowIndex > -1)) {
                    newStartRowKey = isEmptyValue(currentCell.rowKey) ? startRowKey : currentCell.rowKey
                    newEndRowKey = rowKey
                } else {
                    const currentRowIndex = allRowKeys.value.indexOf(rowKey)

                    // 左键点击 || 不在当前选择行内
                    if (
                        mouseEventClickType === MOUSE_EVENT_CLICK_TYPE.LEFT_MOUSE ||
                        currentRowIndex < startRowKeyIndex ||
                        currentRowIndex > endRowKeyIndex
                    ) {
                        newStartRowKey = rowKey
                        newEndRowKey = rowKey
                    }
                }

                bodyIndicatorRowKeysChange({
                    startRowKey: newStartRowKey,
                    endRowKey: newEndRowKey,
                })
            } else {
                // body cell mousedown
                // console.log(`改isBodyCellMousedown true ing👇`)
                a.isBodyCellMousedown = true
                const isClearByRightClick = isClearSelectionByBodyCellRightClick({
                    mouseEventClickType,
                    cellData: {
                        rowKey,
                        colKey,
                    },
                    cellSelectionData: a.cellSelectionData,
                    cellSelectionRangeData: a.cellSelectionRangeData,
                    colgroups: a.colgroups,
                    allRowKeys: allRowKeys.value,
                })

                if (isClearByRightClick) {
                    // clear header indicator colKeys
                    clearHeaderIndicatorColKeys()
                    // clear body indicator colKeys
                    clearBodyIndicatorRowKeys()

                    if (shiftKey && currentCell.rowIndex > -1) {
                        cellSelectionNormalEndCellChange({
                            rowKey,
                            colKey,
                        })
                    } else {
                        // cell selection by click
                        cellSelectionByClick({ rowData, column })
                        clearCellSelectionNormalEndCell()
                    }
                }
            }

            if (editOption) {
                编辑单元格ByClick({
                    isDblclick: false,
                    rowKey,
                    colKey,
                })
            }
        }

        const bodyCellMouseover = ({ event, rowData, column }) => {
            // console.log(`bodyCellMouseover ing👇`)
            // console.log(`a.isBodyCellMousedown 👉`, a.isBodyCellMousedown)
            const { rowKeyFieldName } = props
            const rowKey = getRowKey(rowData, rowKeyFieldName)
            const colKey = column.key
            if (a.isBodyCellMousedown) {
                // 操作列不能单元格选中
                const 是操作列否 = isOperationColumn(colKey, a.colgroups)
                console.log(`是操作列否 👉`, 是操作列否)
                if (是操作列否) {
                    return false
                }

                cellSelectionNormalEndCellChange({
                    rowKey,
                    colKey,
                })
            }
            if (a.isBodyOperationColumnMousedown) {
                bodyIndicatorRowKeysChange({
                    startRowKey: a.bodyIndicatorRowKeys.startRowKey,
                    endRowKey: rowKey,
                })
            }

            // 允许在body cell mouseover 里补充 header indicator 信息
            if (a.isHeaderCellMousedown) {
                headerIndicatorColKeysChange({
                    startColKey: a.headerIndicatorColKeys.startColKey,
                    endColKey: colKey,
                })
            }

            if (a.isAutofillStarting) {
                // 操作列不能autofilling 效果
                if (isOperationColumn(colKey, a.colgroups)) {
                    return false
                }
                cellSelectionAutofillCellChange({
                    rowKey,
                    colKey,
                })
            }
        }

        const bodyCellMousemove = ({ event, rowData, column }) => {
            // console.log(`bodyCellMousemove ing👇`)
            triggerHook(HOOKS_NAME.BODY_CELL_MOUSEMOVE, {
                event,
                column,
            })
        }

        const bodyCellMouseup = ({ event, rowData, column }) => {
            // feature...
        }

        const headerCellClick = ({ event, column }) => {
            // feature...
        }

        const headerCellContextmenu = ({ event, column }) => {
            setContextmenuOptions(column)
        }

        const setContextmenuOptions = column => {
            const { contextmenuHeaderOption, contextmenuBodyOption } = props
            // header contextmenu
            if (contextMenuType.value === CONTEXTMENU_TYPES.HEADER_CONTEXTMENU) {
                // set header contextmenu options before contextmen show
                a.contextmenuOptions = setHeaderContextmenuOptions({
                    column,
                    contextmenuHeaderOption: contextmenuHeaderOption,
                    cellSelectionRangeData: a.cellSelectionRangeData,
                    colgroups: a.colgroups,
                    allRowKeys: allRowKeys.value,
                    headerIndicatorColKeys: a.headerIndicatorColKeys,
                    enableHeaderContextmenu: a.enableHeaderContextmenu,
                    t,
                })
            }
            // body contextmenu
            else {
                // set body contextmenu options before contextmen show
                a.contextmenuOptions = setBodyContextmenuOptions({
                    enableBodyContextmenu: enableBodyContextmenu.value,
                    contextmenuBodyOption: contextmenuBodyOption,
                    cellSelectionRangeData: a.cellSelectionRangeData,
                    colgroups: a.colgroups,
                    allRowKeys: allRowKeys.value,
                    bodyIndicatorRowKeys: a.bodyIndicatorRowKeys,
                    t,
                })
            }
        }

        const headerCellMousedown = ({ event, column }) => {
            if (!enableCellSelection.value) {
                return false
            }
            a.isHeaderCellMousedown = true
            const { shiftKey } = event
            // clear body indicator colKeys
            clearBodyIndicatorRowKeys()

            let colKeys
            if (isGroupHeader) {
                colKeys = getColKeysByHeaderColumn({
                    headerColumnItem: column,
                })
            } else {
                colKeys = [column.key]
            }
            const currentCellStartColKey = colKeys[0]
            const currentCellEndColKey = colKeys[colKeys.length - 1]
            const { currentCell } = a.cellSelectionData
            if (isOperationColumn(column.key, a.colgroups)) {
                // clear cell selection
                clearCellSelectionCurrentCell()
                clearCellSelectionNormalEndCell()
                instance.proxy.$nextTick(() => {
                    setAllCellSelection()
                })
                return false
            }

            // 需要先将之前选中单元格元素清空
            if (isEmptyValue(headerIndicatorColKeys.startColKey)) {
                // 值的比较（currentCell.colKey 会变化）
                if (JSON.stringify(colKeys) != JSON.stringify([currentCell.colKey])) {
                    instance.proxy.$refs[a.cellSelectionRef].clearCurrentCellRect()
                }
                instance.proxy.$refs[a.cellSelectionRef].clearNormalEndCellRect()
            }

            const { startColKey, endColKey, startColKeyIndex, endColKeyIndex } = headerIndicatorColKeys

            let newStartColKey = startColKey
            let newEndColKey = endColKey
            if (shiftKey) {
                if (isEmptyValue(startColKey)) {
                    if (!isEmptyValue(currentCell.colKey)) {
                        const leftColKey = getLeftmostColKey({
                            colgroups: a.colgroups,
                            colKeys: colKeys.concat([currentCell.colKey]),
                        })

                        newStartColKey = currentCell.colKey
                        if (leftColKey === currentCell.colKey) {
                            newEndColKey = currentCellEndColKey
                        } else {
                            newEndColKey = currentCellStartColKey
                        }
                    } else {
                        newStartColKey = currentCellStartColKey
                        newEndColKey = currentCellEndColKey
                    }
                } else {
                    newStartColKey = startColKey
                    const leftColKey = getLeftmostColKey({
                        colgroups: a.colgroups,
                        colKeys: colKeys.concat([startColKey]),
                    })

                    if (leftColKey === startColKey) {
                        newEndColKey = currentCellEndColKey
                    } else {
                        newEndColKey = currentCellStartColKey
                    }
                }
            } else {
                const mouseEventClickType = getMouseEventClickType(event)
                const currentCellStartColIndex = a.colgroups.findIndex(x => x.key === currentCellEndColKey)
                const currentCellEndColIndex = a.colgroups.findIndex(x => x.key === currentCellStartColKey)
                // 左键点击 || 不在当前选择列内
                if (
                    mouseEventClickType === MOUSE_EVENT_CLICK_TYPE.LEFT_MOUSE ||
                    currentCellStartColIndex < startColKeyIndex ||
                    currentCellEndColIndex < startColKeyIndex ||
                    currentCellStartColIndex > endColKeyIndex ||
                    currentCellEndColIndex > endColKeyIndex
                ) {
                    newStartColKey = currentCellStartColKey
                    newEndColKey = currentCellEndColKey
                }
            }

            headerIndicatorColKeysChange({
                startColKey: newStartColKey,
                endColKey: newEndColKey,
            })
        }

        const headerCellMouseover = ({ event, column }) => {
            if (a.isHeaderCellMousedown && !isOperationColumn(column.key, a.colgroups)) {
                let colKeys
                if (isGroupHeader) {
                    colKeys = getColKeysByHeaderColumn({
                        headerColumnItem: column,
                    })
                } else {
                    colKeys = [column.key]
                }

                const leftColKey = getLeftmostColKey({
                    colgroups: a.colgroups,
                    colKeys: colKeys.concat([headerIndicatorColKeys.startColKey]),
                })

                let endColKey
                if (leftColKey === headerIndicatorColKeys.startColKey) {
                    endColKey = colKeys[colKeys.length - 1]
                } else {
                    endColKey = colKeys[0]
                }
                headerIndicatorColKeysChange({
                    startColKey: headerIndicatorColKeys.startColKey,
                    endColKey,
                })
            }
        }

        const headerCellMousemove = ({ event, column }) => {
            // console.log(`监听到 headerCellMousemove ing👇`)
            triggerHook(HOOKS_NAME.HEADER_CELL_MOUSEMOVE, {
                event,
                column,
            })
        }

        const headerCellMouseleave = ({ event, column }) => {
            // 如果按照之前的逻辑，这里可能需要补充更多功能，目前只是保持原逻辑的占位
        }

        const headerMouseleave = event => {
            setIsColumnResizerHover(false)
        }

        const tableContainerMouseup = () => {
            a.isHeaderCellMousedown = false
            // console.log(`取消 isBodyCellMousedown  ing👇`)
            a.isBodyCellMousedown = false
            a.isBodyOperationColumnMousedown = false
            a.isAutofillStarting = false
        }

        const cellSelectionCornerMousedown = ({ event }) => {
            a.isAutofillStarting = true
        }

        const cellSelectionCornerMouseup = ({ event }) => {
            a.isAutofillStarting = false
        }

        const isEditColumn = colKey => {
            return a.colgroups.some(x => x.key === colKey && x.edit)
        }

        const 编辑单元格ByClick = ({ isDblclick, rowKey, colKey }) => {
            // console.log(`编辑单元格ByClick ing👇`)
            if (!hasEditColumn.value) return false
            if (isEmptyValue(rowKey) || isEmptyValue(colKey)) {
                return false
            }
            if (a.editingCell && a.editingCell.rowKey === rowKey && a.editingCell.colKey === colKey) {
                return false
            }
            if (isCellEditing.value) {
                停止编辑单元格()
            }

            if (isDblclick && isEditColumn(colKey)) {
                a.enableStopEditing = false
                编辑单元格({
                    rowKey,
                    colKey,
                })
            } else {
                a.enableStopEditing = true
            }
        }

        const 设置当前编辑单元格 = ({ rowKey, colKey, column, row }) => {
            // console.log(`设置当前编辑单元格 ing👇`)
            a.editingCell = {
                rowKey,
                row: util.深拷贝(row),
                colKey,
                column,
            }
        }

        const 改单元格 = value => {
            let { row, column } = a.editingCell
            row[column.field] = value
            a.editingCell.row = row
        }

        const 删单元格 = () => {
            a.editingCell = {
                rowKey: "",
                colKey: "",
                row: null,
                column: null,
            }
        }

        const contextmenuItemClick = type => {
            if (contextMenuType.value === CONTEXTMENU_TYPES.HEADER_CONTEXTMENU) {
                headerContextmenuItemClick(type)
            }
            // body contextmenu
            else {
                bodyContextmenuItemClick(type)
            }
        }

        const headerContextmenuItemClick = type => {
            const { rowKey, colKey } = a.cellSelectionData.currentCell
            const { contextmenuHeaderOption } = props
            const { afterMenuClick } = contextmenuHeaderOption

            if (!isEmptyValue(rowKey) && !isEmptyValue(colKey)) {
                let selectionRangeKeys = getSelectionRangeKeys({
                    cellSelectionRangeData: a.cellSelectionRangeData,
                })

                let selectionRangeIndexes = getSelectionRangeIndexes({
                    cellSelectionRangeData: a.cellSelectionRangeData,
                    colgroups: a.colgroups,
                    allRowKeys: allRowKeys.value,
                })

                if (isFunction(afterMenuClick)) {
                    const callback = afterMenuClick({
                        type,
                        selectionRangeKeys,
                        selectionRangeIndexes,
                    })
                    if (isBoolean(callback) && !callback) {
                        return false
                    }
                }
                const editInputEditor = instance.proxy.$refs[a.editInputRef]

                // cut
                if (CONTEXTMENU_NODE_TYPES.CUT === type) {
                    editInputEditor.textareaSelect()
                    document.execCommand("cut")
                }
                // copy
                else if (CONTEXTMENU_NODE_TYPES.COPY === type) {
                    editInputEditor.textareaSelect()
                    document.execCommand("copy")
                }
                // empty column
                else if (CONTEXTMENU_NODE_TYPES.EMPTY_COLUMN === type) {
                    deleteCellSelectionRangeValue()
                }
                // left fixed column to
                else if (CONTEXTMENU_NODE_TYPES.LEFT_FIXED_COLUMN_TO === type) {
                    a.cloneColumns = setColumnFixed({
                        cloneColumns: a.cloneColumns,
                        cellSelectionRangeData: a.cellSelectionRangeData,
                        fixedType: COLUMN_FIXED_TYPE.LEFT,
                        colgroups: a.colgroups,
                        enableColumnResize: enableColumnResize.value,
                    })
                }
                // cancel left fixed column to
                else if (CONTEXTMENU_NODE_TYPES.CANCEL_LEFT_FIXED_COLUMN_TO === type) {
                    a.cloneColumns = cancelColumnFixed({
                        cloneColumns: a.cloneColumns,
                        colgroups: a.colgroups,
                        fixedType: COLUMN_FIXED_TYPE.LEFT,
                        enableColumnResize: enableColumnResize.value,
                    })
                }
                // right fixed column to
                else if (CONTEXTMENU_NODE_TYPES.RIGHT_FIXED_COLUMN_TO === type) {
                    a.cloneColumns = setColumnFixed({
                        cloneColumns: a.cloneColumns,
                        cellSelectionRangeData: a.cellSelectionRangeData,
                        fixedType: COLUMN_FIXED_TYPE.RIGHT,
                        colgroups: a.colgroups,
                        enableColumnResize: enableColumnResize.value,
                    })
                }
                // cancel right fixed column to
                else if (CONTEXTMENU_NODE_TYPES.CANCEL_RIGHT_FIXED_COLUMN_TO === type) {
                    a.cloneColumns = cancelColumnFixed({
                        cloneColumns: a.cloneColumns,
                        colgroups: a.colgroups,
                        fixedType: COLUMN_FIXED_TYPE.RIGHT,
                        enableColumnResize: enableColumnResize.value,
                    })
                }
            }
        }

        const bodyContextmenuItemClick = type => {
            const { rowKey, colKey } = a.cellSelectionData.currentCell
            const { tableData, contextmenuBodyOption, rowKeyFieldName } = props
            const { afterMenuClick } = contextmenuBodyOption
            if (!isEmptyValue(rowKey) && !isEmptyValue(colKey)) {
                let selectionRangeKeys = getSelectionRangeKeys({
                    cellSelectionRangeData: a.cellSelectionRangeData,
                })
                let selectionRangeIndexes = getSelectionRangeIndexes({
                    cellSelectionRangeData: a.cellSelectionRangeData,
                    colgroups: a.colgroups,
                    allRowKeys: allRowKeys.value,
                })
                if (isFunction(afterMenuClick)) {
                    const callback = afterMenuClick({
                        type,
                        selectionRangeKeys,
                        selectionRangeIndexes,
                    })
                    if (isBoolean(callback) && !callback) {
                        return false
                    }
                }
                const { startRowIndex, endRowIndex } = selectionRangeIndexes
                const currentRowIndex = allRowKeys.value.findIndex(x => x === rowKey)
                const editInputEditor = instance.proxy.$refs[a.editInputRef]
                if (CONTEXTMENU_NODE_TYPES.CUT === type) {
                    editInputEditor.textareaSelect()
                    document.execCommand("cut")
                } else if (CONTEXTMENU_NODE_TYPES.COPY === type) {
                    editInputEditor.textareaSelect()
                    document.execCommand("copy")
                } else if (CONTEXTMENU_NODE_TYPES.REMOVE_ROW === type) {
                    tableData.splice(startRowIndex, endRowIndex - startRowIndex + 1)
                }
                // empty rows
                else if (CONTEXTMENU_NODE_TYPES.EMPTY_ROW === type) {
                    deleteCellSelectionRangeValue()
                }
                // empty rows
                else if (CONTEXTMENU_NODE_TYPES.EMPTY_CELL === type) {
                    deleteCellSelectionRangeValue()
                }
                // insert row above
                else if (CONTEXTMENU_NODE_TYPES.INSERT_ROW_ABOVE === type) {
                    tableData.splice(
                        currentRowIndex,
                        0,
                        createEmptyRowData({ colgroups: a.colgroups, rowKeyFieldName })
                    )
                }
                // insert row below
                else if (CONTEXTMENU_NODE_TYPES.INSERT_ROW_BELOW === type) {
                    tableData.splice(
                        currentRowIndex + 1,
                        0,
                        createEmptyRowData({ colgroups: a.colgroups, rowKeyFieldName })
                    )
                }
            }
        }

        const editorCopy = event => {
            if (!enableClipboard.value) return false
            const { tableData, clipboardOption } = props
            // 正在编辑的单元格不进行自定义复制功能
            if (isCellEditing.value) return false

            const { copy, beforeCopy: beforeCopyCallback, afterCopy: afterCopyCallback } = clipboardOption || {}
            if (isBoolean(copy) && !copy) {
                return false
            }
            event.preventDefault()
            const selectionRangeData = getSelectionRangeData({
                cellSelectionRangeData: a.cellSelectionRangeData,
                resultType: "flat",
                tableData,
                colgroups: a.colgroups,
                allRowKeys: allRowKeys.value,
            })

            const response = onBeforeCopy({
                cellSelectionRangeData: a.cellSelectionRangeData,
                selectionRangeData,
                colgroups: a.colgroups,
                allRowKeys: allRowKeys.value,
            })

            if (isFunction(beforeCopyCallback)) {
                const allowCoping = beforeCopyCallback(response)
                if (isBoolean(allowCoping) && !allowCoping) {
                    return false
                }
            }

            onAfterCopy({ event, selectionRangeData })

            if (isFunction(afterCopyCallback)) {
                afterCopyCallback(response)
            }
        }

        const editorPaste = event => {
            if (!enableClipboard.value) return false
            const { tableData, rowKeyFieldName, clipboardOption } = props

            // 正在编辑的单元格不进行自定义粘贴功能
            if (isCellEditing.value) return false

            const { paste, beforePaste: beforePasteCallback, afterPaste: afterPasteCallback } = clipboardOption || {}

            if (isBoolean(paste) && !paste) {
                return false
            }

            event.preventDefault()

            const response = onBeforePaste({
                event,
                cellSelectionRangeData: a.cellSelectionRangeData,
                colgroups: a.colgroups,
                allRowKeys: allRowKeys.value,
                rowKeyFieldName: rowKeyFieldName,
            })

            if (response && Array.isArray(response.data) && response.data.length) {
                if (isFunction(beforePasteCallback)) {
                    const allowPasting = beforePasteCallback(response)
                    if (isBoolean(allowPasting) && !allowPasting) {
                        return false
                    }
                }
                // change table cell data
                onAfterPaste({
                    tableData: tableData,
                    beforePasteResponse: response,
                })

                if (isFunction(afterPasteCallback)) {
                    afterPasteCallback(response)
                }

                const { startColKey, endColKey, startRowKey, endRowKey } = response.selectionRangeKeys

                改变选中单元格({
                    rowKey: startRowKey,
                    colKey: startColKey,
                })

                cellSelectionNormalEndCellChange({
                    rowKey: endRowKey,
                    colKey: endColKey,
                })

                // clipboard cell value change
                triggerHook(HOOKS_NAME.CLIPBOARD_CELL_VALUE_CHANGE)
            }
        }

        const editorCut = event => {
            if (!enableClipboard.value) return false
            const { tableData, clipboardOption } = props

            // 正在编辑的单元格不进行自定义剪切功能
            if (isCellEditing.value) return false

            const { cut, beforeCut: beforeCutCallback, afterCut: afterCutCallback } = clipboardOption || {}

            if (isBoolean(cut) && !cut) {
                return false
            }

            event.preventDefault()

            const selectionRangeData = getSelectionRangeData({
                cellSelectionRangeData: a.cellSelectionRangeData,
                resultType: "flat",
                tableData,
                colgroups: a.colgroups,
                allRowKeys: allRowKeys.value,
            })

            const response = onBeforeCut({
                cellSelectionRangeData: a.cellSelectionRangeData,
                selectionRangeData,
                colgroups: a.colgroups,
                allRowKeys: allRowKeys.value,
            })

            if (isFunction(beforeCutCallback)) {
                const allowCuting = beforeCutCallback(response)
                if (isBoolean(allowCuting) && !allowCuting) {
                    return false
                }
            }

            onAfterCut({
                event,
                tableData,
                colgroups: a.colgroups,
                selectionRangeData,
                selectionRangeIndexes: response.selectionRangeIndexes,
            })

            if (isFunction(afterCutCallback)) {
                afterCutCallback(response)
            }
        }

        const deleteCellSelectionRangeValue = () => {
            if (!enableClipboard.value) return false
            const { tableData, clipboardOption } = props

            // 正在编辑的单元格不进行删除区域单元格功能
            if (isCellEditing.value) return false

            const {
                // delete is key word
                delete: delete2,
                beforeDelete: beforeDeleteCallback,
                afterDelete: afterDeleteCallback,
            } = clipboardOption || {}

            if (isBoolean(delete2) && !delete2) {
                return false
            }

            const selectionRangeData = getSelectionRangeData({
                cellSelectionRangeData: a.cellSelectionRangeData,
                resultType: "flat",
                tableData,
                colgroups: a.colgroups,
                allRowKeys: allRowKeys.value,
            })

            const response = onBeforeDelete({
                cellSelectionRangeData: a.cellSelectionRangeData,
                selectionRangeData,
                colgroups: a.colgroups,
                allRowKeys: allRowKeys.value,
            })

            if (isFunction(beforeDeleteCallback)) {
                const allowDeleting = beforeDeleteCallback(response)
                if (isBoolean(allowDeleting) && !allowDeleting) {
                    return false
                }
            }

            onAfterDelete({
                tableData,
                colgroups: a.colgroups,
                selectionRangeIndexes: response.selectionRangeIndexes,
            })

            if (isFunction(afterDeleteCallback)) {
                afterDeleteCallback(response)
            }
        }

        const setRangeCellSelectionByHeaderIndicator = () => {
            const { startColKey, endColKey } = headerIndicatorColKeys

            if (isEmptyValue(startColKey) || isEmptyValue(endColKey)) {
                return false
            }

            改变选中单元格({
                rowKey: allRowKeys.value[0],
                colKey: startColKey,
            })

            cellSelectionNormalEndCellChange({
                rowKey: allRowKeys.value[allRowKeys.value.length - 1],
                colKey: endColKey,
            })
        }

        const setRangeCellSelectionByBodyIndicator = () => {
            const { startRowKey, endRowKey } = a.bodyIndicatorRowKeys

            if (isEmptyValue(startRowKey) || isEmptyValue(endRowKey)) {
                return false
            }

            if (a.colgroups.length > 1) {
                改变选中单元格({
                    rowKey: startRowKey,
                    colKey: a.colgroups[1].key,
                })

                cellSelectionNormalEndCellChange({
                    rowKey: endRowKey,
                    colKey: a.colgroups[a.colgroups.length - 1].key,
                })
            }
        }

        const setIsColumnResizerHover = val => {
            a.isColumnResizerHover = val
        }

        const setIsColumnResizing = val => {
            a.isColumnResizing = val
            // console.log(`a.isColumnResizing 👉`, a.isColumnResizing)
        }

        const 设置选中区域 = ({ rowKey, colKey, isScrollToRow = true }) => {
            // console.log(`设置选中区域 👉`,设置选中区域)
            if (!enableCellSelection.value) return false

            if (!isEmptyValue(rowKey) && !isEmptyValue(colKey)) {
                改变选中单元格({
                    rowKey,
                    colKey,
                })

                const column = getColumnByColkey(colKey, a.colgroups)
                columnToVisible(column)
                if (isScrollToRow) {
                    scrollToRowKey({ rowKey })
                }
            }
        }

        const setRangeCellSelection = ({
            startRowKey,
            startColKey,
            endRowKey,
            endColKey,
            isScrollToStartCell = false,
        }) => {
            if (!enableCellSelection.value) {
                return false
            }

            if (
                isEmptyValue(startRowKey) ||
                isEmptyValue(startColKey) ||
                isEmptyValue(endRowKey) ||
                isEmptyValue(endColKey)
            ) {
                return false
            }

            改变选中单元格({
                rowKey: startRowKey,
                colKey: startColKey,
            })

            cellSelectionNormalEndCellChange({
                rowKey: endRowKey,
                colKey: endColKey,
            })

            // row to visible
            if (isScrollToStartCell) {
                const column = getColumnByColkey(startColKey, a.colgroups)
                // column to visible
                columnToVisible(column)
                scrollToRowKey({ rowKey: startRowKey })
            }
        }

        const getRangeCellSelection = () => {
            const { rowKey, colKey } = a.cellSelectionData.currentCell
            if (!isEmptyValue(rowKey) && !isEmptyValue(colKey)) {
                let selectionRangeKeys = getSelectionRangeKeys({
                    cellSelectionRangeData: a.cellSelectionRangeData,
                })
                let selectionRangeIndexes = getSelectionRangeIndexes({
                    cellSelectionRangeData: a.cellSelectionRangeData,
                    colgroups: a.colgroups,
                    allRowKeys: allRowKeys.value,
                })

                return {
                    selectionRangeKeys,
                    selectionRangeIndexes,
                }
            }
        }

        const setAllCellSelection = () => {
            if (!enableCellSelection.value) {
                return false
            }

            if (a.colgroups.length) {
                const colKeys = a.colgroups.filter(x => !x.operationColumn).map(x => x.key)

                if (colKeys.length) {
                    headerIndicatorColKeysChange({
                        startColKey: colKeys[0],
                        endColKey: colKeys[colKeys.length - 1],
                    })
                }
            }

            if (allRowKeys.value.length) {
                bodyIndicatorRowKeysChange({
                    startRowKey: allRowKeys.value[0],
                    endRowKey: allRowKeys.value[allRowKeys.value.length - 1],
                })
            }
        }

        const hideColumnsByKeys = keys => {
            if (!isEmptyArray(keys)) {
                // 将要隐藏的列添加到 a.hiddenColumns 中
                // Add the columns you want to hide to hidden columns
                a.a.hiddenColumns = Array.from(new Set(a.a.hiddenColumns.concat(keys)))

                showOrHideColumns()
            }
        }

        const showColumnsByKeys = keys => {
            if (!isEmptyArray(keys)) {
                // 将要显示的列从 a.hiddenColumns 中移除
                // Remove the columns to show from hidden columns
                for (let i = keys.length - 1; i >= 0; i--) {
                    const delIndex = a.a.hiddenColumns.indexOf(keys[i])
                    if (delIndex > -1) {
                        a.a.hiddenColumns.splice(delIndex, 1)
                    }
                }

                showOrHideColumns()
            }
        }

        expose({ hideColumnsByKeys, showColumnsByKeys })

        const scrollTo = option => {
            scrollTo(instance.proxy.$refs[a.tableContainerRef], option)
        }

        const scrollToRowKey = ({ rowKey }) => {
            if (isEmptyValue(rowKey)) {
                console.warn("Row key can't be empty!")
                return false
            }

            let scrollTop = 0

            const tableContainerRef = instance.proxy.$refs[a.tableContainerRef]

            if (isVirtualScroll.value) {
                const position = a.virtualScrollPositions.find(x => x.rowKey === rowKey)

                if (position) {
                    scrollTop = position.top
                }

                // fix bug #470
                setTimeout(() => {
                    scrollTo(tableContainerRef, {
                        top: scrollTop,
                        behavior: "auto",
                    })
                }, 200)
            } else {
                const rowEl = instance.proxy.$el.querySelector(
                    `tbody tr[${COMPS_CUSTOM_ATTRS.BODY_ROW_KEY}="${rowKey}"]`
                )
                scrollTop = rowEl.offsetTop - headerTotalHeight.value
            }

            scrollTo(tableContainerRef, {
                top: scrollTop,
                behavior: isVirtualScroll.value ? "auto" : "smooth",
            })
        }

        const scrollToColKey = ({ colKey }) => {
            const column = getColumnByColkey(colKey, a.colgroups)
            if (column) {
                columnToVisible(column)
            }
        }

        const 编辑单元格 = ({ rowKey, colKey, defaultValue }) => {
            const { editOption, rowKeyFieldName, tableData } = props
            // console.log(`编辑单元格 ing👇`)
            if (!editOption) return false
            let currentRow = tableData.find(x => x[rowKeyFieldName] === rowKey)
            currentRow = util.深拷贝(currentRow)
            // 调用API编辑的情况，需要关闭之前编辑的单元格
            if (a.editingCell.rowKey === rowKey && a.editingCell.colKey === colKey) {
                return false
            }
            const currentColumn = a.colgroups.find(x => x.key === colKey)
            // 当前列是否可编辑
            if (!currentColumn.edit) {
                return false
            }
            const { beforeStartCellEditing } = editOption
            if (isFunction(beforeStartCellEditing)) {
                const allowContinue = beforeStartCellEditing({
                    row: util.深拷贝(currentRow),
                    column: currentColumn,
                    cellValue: isDefined(defaultValue) ? defaultValue : currentRow[currentColumn.field],
                })
                if (isBoolean(allowContinue) && !allowContinue) {
                    return false
                }
            }

            // 给当前列赋默认值
            if (isDefined(defaultValue)) {
                a.editorInputStartValue = defaultValue
                // doesn't change cell original value
                currentRow[currentColumn.field] = defaultValue
            } else {
                a.editorInputStartValue = currentRow[currentColumn.field]
            }

            if (
                a.cellSelectionData.currentCell.colKey !== colKey ||
                a.cellSelectionData.currentCell.rowKey !== rowKey
            ) {
                改变选中单元格({
                    rowKey,
                    colKey,
                })
            }

            设置当前编辑单元格({
                rowKey,
                colKey,
                column: currentColumn,
                row: util.深拷贝(currentRow),
            })
        }

        const 停止编辑单元格 = () => {
            const { editOption } = props
            if (!editOption) return false
            // clear editor input start value
            a.editorInputStartValue = ""
            if (isCellEditing.value) {
                保存单元格()
            }
        }

        const setHighlightRow = ({ rowKey }) => {
            // console.log(`setHighlightRow ing👇`)
            a.highlightRowKey = rowKey
        }
        //#endregion

        //#region  watch
        // watch tableData
        watch(
            () => props.tableData,
            (newVal, oldVal) => {
                initVirtualScrollPositions()
                if (oldVal) {
                    a.initVirtualScroll()
                }
                // oldTableData = oldVal
            },
            { immediate: true }
        )

        watch(
            allRowKeys,
            newVal => {
                if (Array.isArray(newVal)) {
                    const { currentCell } = a.cellSelectionData
                    if (currentCell.rowIndex > -1) {
                        if (newVal.indexOf(currentCell.rowKey) === -1) {
                            a.clearCellSelectionCurrentCell()
                        }
                    }
                }
            },
            { immediate: false }
        )

        // watch columns
        watch(
            () => props.columns,
            (newVal, oldVal) => {
                // console.log(`props.columns 变化ing👇`)
                // console.log(`newVal 👉`, newVal)
                // console.log(`oldVal 👉`, oldVal)
                initColumns()
                initGroupColumns()
                initColumnWidthByColumnResize()

                // 排除首次
                if (newVal !== oldVal && oldVal) {
                    a.columnsOptionResetTime++

                    // 需要等待 initColumns 和 initGroupColumns 先执行
                    initScrolling()
                }
                // oldColumns = oldVal
            },
            { immediate: true, deep: true }
        )

        // watch cloneColumns
        watch(
            () => a.cloneColumns,
            () => {
                initGroupColumns()
                initColumnWidthByColumnResize()
                a.columnsOptionResetTime++
                initScrolling()
            },
            { immediate: false }
        )

        // watch a.groupColumns
        watch(
            () => a.groupColumns,
            val => {
                if (!isEmptyArray(val)) {
                    initHeaderRows()
                }
            },
            { immediate: true }
        )

        // watch footerData
        watch(
            () => props.footerData,
            val => {
                if (!isEmptyArray(val)) {
                    initFooterRows()
                }
            },
            { immediate: true }
        )

        // watch virtualScrollOption.enable
        watch(
            () => props.virtualScrollOption?.enable,
            newVal => {
                if (newVal) {
                    initVirtualScrollPositions()
                    initVirtualScroll()
                } else {
                    setTableContentTopValue({ top: 0 })
                }
            },
            { immediate: false }
        )

        // watch a.isAutofillStarting
        watch(
            () => a.isAutofillStarting,
            val => {
                if (!val) {
                    设置选中区域ByAutofill()
                    clearCellSelectionAutofillEndCell()
                }
            }
        )

        // watch(
        //   () => a.parentRendered,
        //   (val) => {
        //     console.log(`a.parentRendered 变化了 val 👉`, val)
        //   },
        //   { immediate: true }
        // )

        // watch a.cellSelectionData.currentCell and a.cellSelectionData.normalEndCell with deep option
        watch(
            () => a.cellSelectionData,
            () => {
                setCurrentCellSelectionType()
            },
            { deep: true, immediate: true }
        )

        watch(
            () => a.headerIndicatorColKeys,
            () => {
                setRangeCellSelectionByHeaderIndicator()
            },
            { deep: true }
        )

        watch(
            () => a.bodyIndicatorRowKeys,
            () => {
                setRangeCellSelectionByBodyIndicator()
            },
            { deep: true }
        )
        //#endregion
        let debouncedBodyCellWidthChange

        onMounted(() => {
            // debouncedBodyCellWidthChange = debounce(bodyCellWidthChange, 0)
            debouncedBodyCellWidthChange = useDebounceFn(bodyCellWidthChange, 0)
            a.parentRendered = true
            a.contextmenuEventTarget = document.querySelector(`.${拼样式名_提前传主名("content")}`)
            emitterOn表格(EMIT_EVENTS.SORT_CHANGE, updateColgroupsBySortChange)
            emitterOn表格(EMIT_EVENTS.CHECKBOX_SELECTED_ALL_CHANGE, selectedAllChange)
            emitterOn表格(EMIT_EVENTS.CHECKBOX_SELECTED_ALL_INFO, setSelectedAllInfo)
            emitterOn表格(EMIT_EVENTS.HEADER_ROW_HEIGHT_CHANGE, headerRowHeightChange)
            emitterOn表格(EMIT_EVENTS.BODY_ROW_HEIGHT_CHANGE, bodyRowHeightChange)
            emitterOn表格(EMIT_EVENTS.FOOTER_ROW_HEIGHT_CHANGE, footRowHeightChange)
            emitterOn表格(EMIT_EVENTS.BODY_CELL_CLICK, bodyCellClick)
            emitterOn表格(EMIT_EVENTS.BODY_CELL_MOUSEOVER, bodyCellMouseover)
            emitterOn表格(EMIT_EVENTS.BODY_CELL_MOUSEDOWN, 单元格鼠标按下)
            emitterOn表格(EMIT_EVENTS.BODY_CELL_MOUSEMOVE, bodyCellMousemove)
            emitterOn表格(EMIT_EVENTS.BODY_CELL_MOUSEUP, bodyCellMouseup)
            emitterOn表格(EMIT_EVENTS.SELECTION_CORNER_MOUSEDOWN, cellSelectionCornerMousedown)
            emitterOn表格(EMIT_EVENTS.SELECTION_CORNER_MOUSEUP, cellSelectionCornerMouseup)
            emitterOn表格(EMIT_EVENTS.AUTOFILLING_DIRECTION_CHANGE, autofillingDirectionChange)
            emitterOn表格(EMIT_EVENTS.BODY_CELL_CONTEXTMENU, bodyCellContextmenu)
            emitterOn表格(EMIT_EVENTS.BODY_CELL_DOUBLE_CLICK, 双击单元格)
            emitterOn表格(EMIT_EVENTS.HEADER_CELL_CLICK, headerCellClick)
            emitterOn表格(EMIT_EVENTS.HEADER_CELL_CONTEXTMENU, headerCellContextmenu)
            emitterOn表格(EMIT_EVENTS.HEADER_CELL_MOUSEDOWN, headerCellMousedown)
            emitterOn表格(EMIT_EVENTS.HEADER_CELL_MOUSEOVER, headerCellMouseover)
            emitterOn表格(EMIT_EVENTS.HEADER_CELL_MOUSEMOVE, headerCellMousemove)
            emitterOn表格(EMIT_EVENTS.HEADER_CELL_MOUSELEAVE, headerCellMouseleave)
            document.addEventListener("keydown", dealKeydownEvent)
            initScrolling()
        })

        onBeforeUnmount(() => {
            document.removeEventListener("keydown", dealKeydownEvent)
        })
        function 改high(params) {
            a.highlightRowKey += 1
        }

        //props 必须写在return 渲染函数内部，不然会丢失响应式
        return () => {
            // 在渲染函数内部解构,是不会丢失响应式的……不停渲染，不停执行，不停解构？
            // console.log(`渲染 ing👇`)
            const {
                rowStyleOption,
                cellSelectionOption,
                rowKeyFieldName,
                tableData,
                editOption,
                maxHeight,
                cellAutofillOption,
                contextmenuHeaderOption,
                contextmenuBodyOption,
                clipboardOption,
            } = props

            const headerProps = {
                class: 拼样式名_提前传主名("header"),
                style: {
                    cursor: a.isColumnResizerHover || a.isColumnResizing ? "col-resize" : "",
                },
                columnsOptionResetTime: a.columnsOptionResetTime,
                tableViewportWidth: a.tableViewportWidth,
                groupColumns: a.groupColumns,
                colgroups: a.colgroups,
                isGroupHeader: a.isGroupHeader,
                fixedHeader: props.fixedHeader,
                checkboxOption: props.checkboxOption,
                sortOption: props.sortOption,
                cellStyleOption: props.cellStyleOption,
                eventCustomOption: props.eventCustomOption,
                headerRows: a.headerRows,
                cellSelectionData: a.cellSelectionData,
                cellSelectionRangeData: a.cellSelectionRangeData,
                headerIndicatorColKeys: a.headerIndicatorColKeys,
                onClick: () => {
                    停止编辑单元格()
                },
                onMouseleave: event => {
                    headerMouseleave(event)
                },
            }

            const bodyProps = {
                ref: a.tableBodyRef,
                class: [拼样式名_提前传主名("body"), tableBodyClass.value],
                tableViewportWidth: a.tableViewportWidth,
                columnsOptionResetTime: a.columnsOptionResetTime,
                colgroups: a.colgroups,
                expandOption: props.expandOption,
                checkboxOption: props.checkboxOption,
                actualRenderTableData: actualRenderTableData.value,
                rowKeyFieldName: props.rowKeyFieldName,
                radioOption: props.radioOption,
                virtualScrollOption: props.virtualScrollOption,
                isVirtualScroll: isVirtualScroll.value,
                cellStyleOption: props.cellStyleOption,
                cellSpanOption: props.cellSpanOption,
                eventCustomOption: props.eventCustomOption,
                cellSelectionOption: props.cellSelectionOption,
                hasFixedColumn: hasFixedColumn.value,
                cellSelectionData: a.cellSelectionData,
                cellSelectionRangeData: a.cellSelectionRangeData,
                allRowKeys: allRowKeys.value,
                editOption: props.editOption,
                highlightRowKey: a.highlightRowKey,
                showVirtualScrollingPlaceholder: a.showVirtualScrollingPlaceholder,
                bodyIndicatorRowKeys: a.bodyIndicatorRowKeys,
                onBodyCellWidthChange: debouncedBodyCellWidthChange,
                on高亮行变化: setHighlightRow,
                // [EMIT_EVENTS.HIGHLIGHT_ROW_CHANGE]: setHighlightRow,
            }

            const footerProps = {
                // class: [拼样式名_提前传主名('footer')],
                colgroups: a.colgroups,
                footerData: props.footerData,
                rowKeyFieldName: props.rowKeyFieldName,
                cellStyleOption: props.cellStyleOption,
                fixedFooter: props.fixedFooter,
                cellSpanOption: props.cellSpanOption,
                eventCustomOption: props.eventCustomOption,
                hasFixedColumn: hasFixedColumn.value,
                allRowKeys: allRowKeys.value,
                footerRows: a.footerRows,
                onClick: () => {
                    停止编辑单元格()
                },
            }

            const tableRootProps = {
                ref: a.tableRootRef,
                class: {
                    "vue-table-root": true,
                },
                on点击单元格: 单元格鼠标按下,
            }

            const tableContainerWrapperProps = {
                ref: a.tableContainerWrapperRef,
                style: tableContainerWrapperStyle.value,
                class: {
                    "ve-table": true,
                    [拼样式名_提前传主名("border-around")]: props.borderAround,
                },
                tagName: "div",
                onDomResizeChange: ({ height }) => {
                    a.tableOffestHeight = height
                    initVirtualScroll()
                    // fixed #404
                    initScrolling()
                    setScrollBarStatus()
                    triggerHook(HOOKS_NAME.TABLE_SIZE_CHANGE)
                },
                // directives: [
                //   {
                //     name: 'click-outside',
                //     value: (e) => {
                //       tableClickOutside(e)
                //     },
                //   },
                // ],
            }

            const tableContainerProps = {
                ref: a.tableContainerRef,
                class: tableContainerClass.value,
                style: tableContainerStyle2.value,
                onScroll: () => {
                    const tableContainerRef = instance.proxy.$refs[a.tableContainerRef]
                    triggerHook(HOOKS_NAME.TABLE_CONTAINER_SCROLL, tableContainerRef)
                    setScrolling(tableContainerRef)
                    if (isVirtualScroll.value) {
                        tableContainerVirtualScrollHandler(tableContainerRef)
                        const {
                            virtualScrollStartIndex: startIndex,
                            previewVirtualScrollStartIndex: previewStartIndex,
                        } = a
                        const differ = Math.abs(startIndex - previewStartIndex)
                        // default placeholder per scrolling row count
                        if (differ > defaultPlaceholderPerScrollingRowCount.value) {
                            showVirtualScrollingPlaceholder.value = true
                        } else {
                            showVirtualScrollingPlaceholder.value = false
                        }
                        debounceScrollEnded()
                    }
                },
                onMouseup: () => {
                    // 事件的先后顺序 containerMouseup > 单元格鼠标按下 > bodyCellMouseup > bodyCellClick
                    tableContainerMouseup()
                },
                onMousemove: event => {
                    // todo
                },
            }

            const tableWrapperProps = {
                ref: a.tableContentWrapperRef,
                class: [拼样式名_提前传主名("content-wrapper")],
                tagName: "div",
                onDomResizeChange: ({ height }) => {
                    // console.log(`tableWrapperProps onDomResizeChange height👉`, height)
                    a.tableHeight = height
                    // console.log(`onDomResizeChange a.tableHeight 👉`, a.tableHeight)
                },
            }

            const tableProps = {
                ref: a.tableRef,
                class: [拼样式名_提前传主名("content"), tableClass.value],
                style: tableStyle.value,
            }

            const selectionProps = {
                ref: a.cellSelectionRef,
                tableEl: instance.proxy.$refs[a.tableRef],
                allRowKeys: allRowKeys.value,
                colgroups: a.colgroups,
                parentRendered: a.parentRendered,
                hooks: { addHook, triggerHook },
                cellSelectionData: a.cellSelectionData,
                isAutofillStarting: a.isAutofillStarting,
                cellSelectionRangeData: a.cellSelectionRangeData,
                currentCellSelectionType: a.currentCellSelectionType,
                showVirtualScrollingPlaceholder: a.showVirtualScrollingPlaceholder,
                isVirtualScroll: isVirtualScroll.value,
                virtualScrollVisibleIndexs: a.virtualScrollVisibleIndexs,
                isCellEditing: isCellEditing.value,
                cellAutofillOption: props.cellAutofillOption,
                onCellSelectionRangeDataChange: newData => {
                    cellSelectionRangeDataChange(newData)
                },
            }

            const editInputProps = {
                ref: a.editInputRef,
                hooks: { addHook, triggerHook },
                parentRendered: a.parentRendered,
                inputStartValue: a.editorInputStartValue,
                rowKeyFieldName: props.rowKeyFieldName,
                tableData: tableData,
                cellSelectionData: a.cellSelectionData,
                colgroups: a.colgroups,
                editingCell: a.editingCell,
                isCellEditing: isCellEditing.value,
                allRowKeys: allRowKeys.value,
                hasXScrollBar: a.hasXScrollBar,
                hasYScrollBar: a.hasYScrollBar,
                hasRightFixedColumn: hasRightFixedColumn.value,
                scrollBarWidth: getScrollBarWidth(),
                // edit input click
                onEditInputClick: () => {
                    a.enableStopEditing = false
                },
                // edit input value change
                onEditInputValueChange: value => {
                    改单元格(value)
                },
                // copy
                onEditInputCopy: e => {
                    editorCopy(e)
                },
                // paste
                onEditInputPaste: e => {
                    editorPaste(e)
                },
                // cut
                onEditInputCut: e => {
                    editorCut(e)
                },
            }

            // 直接在组件上写事件，单元测试无法通过。如 on={{"on-node-click":()=>{}}}
            const contextmenuProps = {
                ref: a.contextmenuRef,
                eventTarget: a.contextmenuEventTarget,
                options: a.contextmenuOptions,
                onNodeClick: type => {
                    contextmenuItemClick(type)
                },
            }

            const columnResizerProps = {
                parentRendered: a.parentRendered,
                tableContainerEl: instance.proxy.$refs[a.tableContainerRef],
                hooks: { addHook, triggerHook },
                colgroups: a.colgroups,
                isColumnResizerHover: a.isColumnResizerHover,
                isColumnResizing: a.isColumnResizing,
                setIsColumnResizerHover: setIsColumnResizerHover,
                setIsColumnResizing: setIsColumnResizing,
                setColumnWidth: setColumnWidth,
                columnWidthResizeOption: props.columnWidthResizeOption,
            }
            //#endregion

            const tableContainerWrapper = withDirectives(
                <VueDomResizeObserver {...tableContainerWrapperProps}>
                    <div {...tableContainerProps}>
                        {getVirtualViewPhantom()}
                        <VueDomResizeObserver {...tableWrapperProps}>
                            <table {...tableProps}>
                                <Colgroup colgroups={a.colgroups} enableColumnResize={enableColumnResize.value} />
                                {props.showHeader && <Header {...headerProps} />}
                                <Body {...bodyProps} />
                                <Footer {...footerProps} class={[拼样式名_提前传主名("footer")]} />
                            </table>
                            {enableCellSelection.value && <Selection {...selectionProps} />}
                        </VueDomResizeObserver>
                    </div>
                    {enableCellSelection.value && <EditInput {...editInputProps} />}
                    {(enableHeaderContextmenu.value || enableBodyContextmenu.value) && (
                        <VeContextmenu {...contextmenuProps} />
                    )}
                    {/* <span>enableColumnResize.value:{`${enableColumnResize.value}`}</span> */}
                    {enableColumnResize.value && <ColumnResizer {...columnResizerProps} />}
                </VueDomResizeObserver>,
                [
                    [
                        clickOutsideDirective,
                        e => {
                            tableClickOutside(e)
                        },
                    ],
                ]
            )

            return (
                <div {...tableRootProps}>
                    {/* <button onClick={改high}>
            a.highlightRowKey {a.highlightRowKey}
          </button> */}
                    {tableContainerWrapper}
                </div>
            )
        }
    },
})
